﻿using System;
using Mono.Cecil.Cil;

namespace Mono.Cecil
{
	// Token: 0x02000075 RID: 117
	internal sealed class GenericParameterResolver
	{
		// Token: 0x060004BE RID: 1214 RVA: 0x0001CA50 File Offset: 0x0001AC50
		internal static TypeReference ResolveReturnTypeIfNeeded(MethodReference methodReference)
		{
			bool flag = methodReference.DeclaringType.IsArray && methodReference.Name == "Get";
			TypeReference result;
			if (flag)
			{
				result = methodReference.ReturnType;
			}
			else
			{
				GenericInstanceMethod genericInstanceMethod = methodReference as GenericInstanceMethod;
				GenericInstanceType genericInstanceType = methodReference.DeclaringType as GenericInstanceType;
				bool flag2 = genericInstanceMethod == null && genericInstanceType == null;
				if (flag2)
				{
					result = methodReference.ReturnType;
				}
				else
				{
					result = GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, genericInstanceType, methodReference.ReturnType);
				}
			}
			return result;
		}

		// Token: 0x060004BF RID: 1215 RVA: 0x0001CAC8 File Offset: 0x0001ACC8
		internal static TypeReference ResolveFieldTypeIfNeeded(FieldReference fieldReference)
		{
			return GenericParameterResolver.ResolveIfNeeded(null, fieldReference.DeclaringType as GenericInstanceType, fieldReference.FieldType);
		}

		// Token: 0x060004C0 RID: 1216 RVA: 0x0001CAF4 File Offset: 0x0001ACF4
		internal static TypeReference ResolveParameterTypeIfNeeded(MethodReference method, ParameterReference parameter)
		{
			GenericInstanceMethod genericInstanceMethod = method as GenericInstanceMethod;
			GenericInstanceType genericInstanceType = method.DeclaringType as GenericInstanceType;
			bool flag = genericInstanceMethod == null && genericInstanceType == null;
			TypeReference result;
			if (flag)
			{
				result = parameter.ParameterType;
			}
			else
			{
				result = GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, genericInstanceType, parameter.ParameterType);
			}
			return result;
		}

		// Token: 0x060004C1 RID: 1217 RVA: 0x0001CB40 File Offset: 0x0001AD40
		internal static TypeReference ResolveVariableTypeIfNeeded(MethodReference method, VariableReference variable)
		{
			GenericInstanceMethod genericInstanceMethod = method as GenericInstanceMethod;
			GenericInstanceType genericInstanceType = method.DeclaringType as GenericInstanceType;
			bool flag = genericInstanceMethod == null && genericInstanceType == null;
			TypeReference result;
			if (flag)
			{
				result = variable.VariableType;
			}
			else
			{
				result = GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, genericInstanceType, variable.VariableType);
			}
			return result;
		}

		// Token: 0x060004C2 RID: 1218 RVA: 0x0001CB8C File Offset: 0x0001AD8C
		private static TypeReference ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance declaringGenericInstanceType, TypeReference parameterType)
		{
			ByReferenceType byReferenceType = parameterType as ByReferenceType;
			bool flag = byReferenceType != null;
			TypeReference result;
			if (flag)
			{
				result = GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, byReferenceType);
			}
			else
			{
				ArrayType arrayType = parameterType as ArrayType;
				bool flag2 = arrayType != null;
				if (flag2)
				{
					result = GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, arrayType);
				}
				else
				{
					GenericInstanceType genericInstanceType = parameterType as GenericInstanceType;
					bool flag3 = genericInstanceType != null;
					if (flag3)
					{
						result = GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, genericInstanceType);
					}
					else
					{
						GenericParameter genericParameter = parameterType as GenericParameter;
						bool flag4 = genericParameter != null;
						if (flag4)
						{
							result = GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, genericParameter);
						}
						else
						{
							RequiredModifierType requiredModifierType = parameterType as RequiredModifierType;
							bool flag5 = requiredModifierType != null && GenericParameterResolver.ContainsGenericParameters(requiredModifierType);
							if (flag5)
							{
								result = GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, requiredModifierType.ElementType);
							}
							else
							{
								bool flag6 = GenericParameterResolver.ContainsGenericParameters(parameterType);
								if (flag6)
								{
									throw new Exception("Unexpected generic parameter.");
								}
								result = parameterType;
							}
						}
					}
				}
			}
			return result;
		}

		// Token: 0x060004C3 RID: 1219 RVA: 0x0001CC60 File Offset: 0x0001AE60
		private static TypeReference ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericParameter genericParameterElement)
		{
			return (genericParameterElement.MetadataType == MetadataType.MVar) ? ((genericInstanceMethod != null) ? genericInstanceMethod.GenericArguments[genericParameterElement.Position] : genericParameterElement) : genericInstanceType.GenericArguments[genericParameterElement.Position];
		}

		// Token: 0x060004C4 RID: 1220 RVA: 0x0001CCA8 File Offset: 0x0001AEA8
		private static ArrayType ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ArrayType arrayType)
		{
			return new ArrayType(GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, genericInstanceType, arrayType.ElementType), arrayType.Rank);
		}

		// Token: 0x060004C5 RID: 1221 RVA: 0x0001CCD4 File Offset: 0x0001AED4
		private static ByReferenceType ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ByReferenceType byReferenceType)
		{
			return new ByReferenceType(GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, genericInstanceType, byReferenceType.ElementType));
		}

		// Token: 0x060004C6 RID: 1222 RVA: 0x0001CCF8 File Offset: 0x0001AEF8
		private static GenericInstanceType ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericInstanceType genericInstanceType1)
		{
			bool flag = !GenericParameterResolver.ContainsGenericParameters(genericInstanceType1);
			GenericInstanceType result;
			if (flag)
			{
				result = genericInstanceType1;
			}
			else
			{
				GenericInstanceType genericInstanceType2 = new GenericInstanceType(genericInstanceType1.ElementType);
				foreach (TypeReference typeReference in genericInstanceType1.GenericArguments)
				{
					bool flag2 = !typeReference.IsGenericParameter;
					if (flag2)
					{
						genericInstanceType2.GenericArguments.Add(GenericParameterResolver.ResolveIfNeeded(genericInstanceMethod, genericInstanceType, typeReference));
					}
					else
					{
						GenericParameter genericParameter = (GenericParameter)typeReference;
						GenericParameterType type = genericParameter.Type;
						GenericParameterType genericParameterType = type;
						if (genericParameterType != GenericParameterType.Type)
						{
							if (genericParameterType == GenericParameterType.Method)
							{
								bool flag3 = genericInstanceMethod == null;
								if (flag3)
								{
									genericInstanceType2.GenericArguments.Add(genericParameter);
								}
								else
								{
									genericInstanceType2.GenericArguments.Add(genericInstanceMethod.GenericArguments[genericParameter.Position]);
								}
							}
						}
						else
						{
							bool flag4 = genericInstanceType == null;
							if (flag4)
							{
								throw new NotSupportedException();
							}
							genericInstanceType2.GenericArguments.Add(genericInstanceType.GenericArguments[genericParameter.Position]);
						}
					}
				}
				result = genericInstanceType2;
			}
			return result;
		}

		// Token: 0x060004C7 RID: 1223 RVA: 0x0001CE34 File Offset: 0x0001B034
		private static bool ContainsGenericParameters(TypeReference typeReference)
		{
			GenericParameter genericParameter = typeReference as GenericParameter;
			bool flag = genericParameter != null;
			bool result;
			if (flag)
			{
				result = true;
			}
			else
			{
				ArrayType arrayType = typeReference as ArrayType;
				bool flag2 = arrayType != null;
				if (flag2)
				{
					result = GenericParameterResolver.ContainsGenericParameters(arrayType.ElementType);
				}
				else
				{
					PointerType pointerType = typeReference as PointerType;
					bool flag3 = pointerType != null;
					if (flag3)
					{
						result = GenericParameterResolver.ContainsGenericParameters(pointerType.ElementType);
					}
					else
					{
						ByReferenceType byReferenceType = typeReference as ByReferenceType;
						bool flag4 = byReferenceType != null;
						if (flag4)
						{
							result = GenericParameterResolver.ContainsGenericParameters(byReferenceType.ElementType);
						}
						else
						{
							SentinelType sentinelType = typeReference as SentinelType;
							bool flag5 = sentinelType != null;
							if (flag5)
							{
								result = GenericParameterResolver.ContainsGenericParameters(sentinelType.ElementType);
							}
							else
							{
								PinnedType pinnedType = typeReference as PinnedType;
								bool flag6 = pinnedType != null;
								if (flag6)
								{
									result = GenericParameterResolver.ContainsGenericParameters(pinnedType.ElementType);
								}
								else
								{
									RequiredModifierType requiredModifierType = typeReference as RequiredModifierType;
									bool flag7 = requiredModifierType != null;
									if (flag7)
									{
										result = GenericParameterResolver.ContainsGenericParameters(requiredModifierType.ElementType);
									}
									else
									{
										GenericInstanceType genericInstanceType = typeReference as GenericInstanceType;
										bool flag8 = genericInstanceType != null;
										if (flag8)
										{
											foreach (TypeReference typeReference2 in genericInstanceType.GenericArguments)
											{
												bool flag9 = GenericParameterResolver.ContainsGenericParameters(typeReference2);
												if (flag9)
												{
													return true;
												}
											}
											result = false;
										}
										else
										{
											bool flag10 = typeReference is TypeSpecification;
											if (flag10)
											{
												throw new NotSupportedException();
											}
											result = false;
										}
									}
								}
							}
						}
					}
				}
			}
			return result;
		}
	}
}
